Java JavaScript Python C# C C++ Go Kotlin PHP Swift R Ruby TypeScript Scala SQL Perl rust VisualBasic Matlab Julia

Abstraction → Abstract Classes

Abstraction

Abstract Classes

Abstract Classes in Python

Abstract classes in Python, facilitated by the `abc` (Abstract Base Classes) module, serve as blueprints for other classes. They define a common interface – a set of methods that *must* be implemented by any concrete class inheriting from them. Crucially, you cannot directly instantiate an abstract class; it's only meant to be a parent for more specialized subclasses. This enforces a consistent structure and behavior across related classes.

Key Features and Benefits

Interface Definition: Abstract classes primarily define a contract. They specify *what* methods subclasses *must* provide, but not *how* those methods are implemented. Encapsulation and Polymorphism: Abstract classes contribute to better code organization and reusability through encapsulation (bundling data and methods) and polymorphism (allowing objects of different classes to respond to the same method call in their own specific way). Code Maintainability: By defining a common interface, abstract classes improve code readability and maintainability, especially in large projects. Changes in the abstract class's interface automatically propagate to all subclasses, ensuring consistency. Early Error Detection: The abstract class mechanism helps catch errors early in the development cycle. If a subclass fails to implement a required method, an error is raised at runtime (or during static analysis with tools like MyPy), preventing unexpected behavior later.

Implementing Abstract Classes with `abc`

The `abc` module provides the necessary tools. Here's how: Import `ABC` and `abstractmethod`:
Importing `ABC` and `abstractmethod` from abc import ABC, abstractmethod

Define an Abstract Class: Create a class inheriting from `ABC`. Methods intended to be abstract are decorated with `@abstractmethod`.
Declaring abstract classes from abc import ABC, abstractmethod class Shape(ABC): # Declare Shape as an abstract class @abstractmethod def area(self): # Abstract method - no implementation pass @abstractmethod def perimeter(self): # Another abstract method pass def describe(self): # Concrete method (can be implemented in the abstract class) print("This is a generic shape.")

Create Concrete Subclasses: Concrete subclasses must provide implementations for all abstract methods defined in the parent abstract class.
Creating concrete subclasses class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.14159 * self.radius * self.radius def perimeter(self): return 2 * 3.14159 * self.radius class Rectangle(Shape): def __init__(self, length, width): self.length = length self.width = width def area(self): return self.length * self.width def perimeter(self): return 2 * (self.length + self.width)

Instantiation and Usage: You can instantiate concrete subclasses, but not the abstract class itself.
instantiate concrete subclasses my_circle = Circle(5) print(f"Circle area: {my_circle.area()}") print(f"Circle perimeter: {my_circle.perimeter()}") my_circle.describe() my_rect = Rectangle(4, 6) print(f"Rectangle area: {my_rect.area()}") print(f"Rectangle perimeter: {my_rect.perimeter()}") my_rect.describe() # This will raise an error: TypeError: Can't instantiate abstract class Shape with abstract methods area, perimeter # my_shape = Shape()

Combining all from abc import ABC, abstractmethod class Shape(ABC): # Declare Shape as an abstract class @abstractmethod def area(self): # Abstract method - no implementation pass @abstractmethod def perimeter(self): # Another abstract method pass def describe(self): # Concrete method (can be implemented in the abstract class) print("This is a generic shape.") class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.14159 * self.radius * self.radius def perimeter(self): return 2 * 3.14159 * self.radius class Rectangle(Shape): def __init__(self, length, width): self.length = length self.width = width def area(self): return self.length * self.width def perimeter(self): return 2 * (self.length + self.width) my_circle = Circle(5) print(f"Circle area: {my_circle.area()}") print(f"Circle perimeter: {my_circle.perimeter()}") my_circle.describe() my_rect = Rectangle(4, 6) print(f"Rectangle area: {my_rect.area()}") print(f"Rectangle perimeter: {my_rect.perimeter()}") my_rect.describe() # This will raise an error: TypeError: Can't instantiate abstract class Shape with abstract methods area, perimeter # my_shape = Shape()

Output

Circle area: 78.53975 Circle perimeter: 31.4159 This is a generic shape. Rectangle area: 24 Rectangle perimeter: 20 This is a generic shape.

Example with Multiple Abstract Methods and Default Implementations:
Example with Multiple Abstract Methods and Default Implementations from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def make_sound(self): pass @abstractmethod def eat(self): pass def sleep(self): # Default implementation in abstract class print("The animal is sleeping.") class Dog(Animal): def make_sound(self): print("Woof!") def eat(self): print("The dog is eating kibble.") class Cat(Animal): def make_sound(self): print("Meow!") def eat(self): print("The cat is eating tuna.") my_dog = Dog() my_dog.make_sound() my_dog.eat() my_dog.sleep() my_cat = Cat() my_cat.make_sound() my_cat.eat() my_cat.sleep()

Output

Woof! The dog is eating kibble. The animal is sleeping. Meow! The cat is eating tuna. The animal is sleeping.

These examples demonstrate how abstract classes provide a powerful mechanism for enforcing structure, promoting code reusability, and improving overall software design in Python. They are particularly beneficial in larger projects where maintaining consistency and managing complex relationships between classes is critical.

Tutorials